package com.legendframework.dao.extension.service;

import com.legendframework.dao.DataResources;
import com.legendframework.dao.extension.exception.ServiceException;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * Service生成器
 *
 * 生成Servcie是实现类
 *
 */
public class ServiceGenerate {

    private final static Map<Class,IService> serviceCache = new HashMap<>();

    private ServiceGenerate(){}

    /**
     * 根据实体类字节码对象生成Dao对象
     * @param serviceCls 实体类字节码对象
     * @param dataResources 数据底层所需数据
     * @param iocHandle IOC容器处理器，预期是需要外层IOC提供实现方法对Service实现类进行动态代理，动态注入
     * @param <S> 实体类类型
     * @return Service对象
     */
    public static <S extends IService> S generate(Class<S> serviceCls , DataResources dataResources, Function<Object,Object> iocHandle){
        try {
            IService serivce = serviceCache.get(serviceCls);
            if (serivce != null) {
                return (S) serivce;
            }
            Constructor<S> constructor = serviceCls.getDeclaredConstructor();
            constructor.setAccessible(true);
            S s = constructor.newInstance();
            //获取generateEntityDao方法
            Method generateEntityDaoMethod = BaseService.class.getDeclaredMethod("generateEntityDao", DataResources.class, Function.class);
            generateEntityDaoMethod.setAccessible(true);
            //初始化Service
            generateEntityDaoMethod.invoke(s,dataResources,iocHandle);
            //存入缓存
            serviceCache.put(serviceCls,s);
            return s;
        } catch (Throwable e) {
            throw new ServiceException(e);
        }
    }

    /**
     * 根据实体类字节码对象生成Dao对象
     * @param serviceCls 实体类字节码对象
     * @param dataResources 数据底层所需数据
     * @param <S> 实体类类型
     * @return Service对象
     */
    public static <S extends IService> S generate(Class<S> serviceCls , DataResources dataResources){
        return generate(serviceCls,dataResources,item -> item);
    }
}
